Concurrent programming for shared-memory multiple processor systems can include the ability for multiple threads to access the same data. The multiple threads execute on multiple processors, multiple processor cores, or other classes of parallelism that are attached to a memory shared between the processors. The shared-memory model is the most commonly deployed method of multithread communication. It allows multithreaded programs to be created in much the same way as sequential programs. In order to implement the shared-memory model, concurrent programming uses care to avoid concurrent access and use of shared data that can create undesirable conditions such as races and the like.
Locks are a common solution to avoid the problem of concurrent access to shared data. Locks are centered on a premise that other threads may also try to access variables accessed by a certain thread, while the variable can only be used by one thread at a time. Locks allow one thread to take control of a variable and prevent other threads from changing the variable until it is unlocked. Lock-based protocols, while popular, are often considered difficult to use. Using locks in a coarse-grained way protects relatively large amounts of data, but generally their use does not scale. Threads block one another even when they do not interfere, and the locks become a source of contention. Alternatively, using locks in a more fine-grained way can mitigate scalability issues, but the locks introduce other problems because the locking conventions to ensure correctness and avoid deadlocks become complex and error prone.
Another solution is to implement applications using transactional memory. Transactional memory systems manage the memory accesses of threads by executing the threads in such a way that the effects of a thread can be rolled back or undone if two or more threads attempt to access the same memory location in a conflicting manner. Transactional memory systems can be implemented using hardware and/or software components. A software transactional memory system can provide semantics in a software runtime library and/or runtime execution environment and/or using compilers. Transactional memory is frequently implemented as a compiler-level concurrency control mechanism for controlling access to shared memory based on the premise that variables read by one thread will likely not be modified by other threads, and thus the variable can be shared without harsh ramifications to the scalability of the program. Tracking memory access in transactional memory systems, however, can possibly add overhead to the execution of programs.
One benefit of transactional memory over coarse-lock-based protocols is increased concurrency. In transactional memory, no thread needs to wait for access to data, and different threads can safely and simultaneously modify disjoint parts of a data structure that would normally be protected under the same lock. Despite the overhead of retrying transactions that fail, in many realistic concurrent programs conflicts arise rarely enough that there can be a performance gain over course-grained lock-based protocols starting from certain number of processors or processor cores.
Despite the promise of transactional memory and being the subject of extensive research, obstacles remain to its widespread use and acceptance. For example, programmers can be reluctant to use transactional memory, because of unfamiliarity and lack of a practical, user-friendly implementation of transactional memory.